package com.shangguigu.array;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author: ZhouBert
 * @date: 2019/9/29
 * @description: eg1.稀疏数组
 * todo:障碍：List<List<>> 不能直接转二维数组
 */
public class SparseArray {

	public static String CATALOGUE_PATH;

	public static String SEPARATOR="\t";

	/**
	 * 定义一个 11*11 的二维数组
	 */
	public static int[][] sourceArray = new int[11][11];

	/**
	 * 定义一个棋盘（11*11 1-白棋；2-黑棋）
	 */
	public static int[][] chessboard = new int[11][11];

	static {
		///对应教材，在 1,2-1;2,3-2
		for (int i = 0; i < sourceArray.length; i++) {
			for (int j = 0; j < sourceArray[i].length; j++) {
				if (i == 1 && j == 2) {
					sourceArray[i][j] = 1;
				} else if (i == 2 && j == 3) {
					sourceArray[i][j] = 2;
				} else {
					sourceArray[i][j] = 0;
				}
			}
		}
		///默认0，那么可以这样
		chessboard[1][2] = 1;
		chessboard[2][3] = 2;
		chessboard[2][4] = 2;
		System.out.println("棋盘初试状态...");
		///todo: 1.foreach 出 行，再对行进行遍历
		for (int[] row : chessboard) {
			for (int data : row) {
				System.out.printf("%d\t", data);
			}
			System.out.println();
		}
	}

	public static Integer[][] sparse(int[][] entity) {
		//第一行-行数 列数 有数值个数
		List<List<Integer>> result = new ArrayList<>();
		List<Integer> firstList = new ArrayList<>();
		firstList.add(entity.length);
		firstList.add(entity[0].length);
		result.add(firstList);
		int sum = 0;
		for (int i = 0; i < entity.length; i++) {
			for (int j = 0; j < entity[i].length; j++) {
				if (entity[i][j] != 0) {
					sum++;
					List<Integer> tempList = new ArrayList<>();
					tempList.add(i);
					tempList.add(j);
					tempList.add(entity[i][j]);
					result.add(tempList);
				}
			}
		}
		firstList.add(sum);
		///将 List<List<>> 转为二维数组
		Integer[][] arrayResult = new Integer[result.size()][result.get(0).size()];
		for (int i = 0; i < result.size(); i++) {
			Integer[] strings = new Integer[result.get(0).size()];
			arrayResult[i] = result.get(i).toArray(strings);
		}
		return arrayResult;
	}

	/**
	 * 打印二维数组
	 */
	public static void print(int[][] doubleArray){
		for (int[] row :
				doubleArray) {
			for (int data :
					row) {
				System.out.printf("%d\t", data);
			}
			System.out.println();
		}
	}

	/**
	 * 将二维数组转稀疏数组（优化）-存盘-还原
	 * 中力，江报
	 * @param args
	 */
	public static void main(String[] args) {
		///用 json 的方式进行打印
		///System.out.println(Arrays.deepToString(SparseArray.sourceArray));
		for (int i = 0; i < sourceArray.length; i++) {
			System.out.println(Arrays.toString(sourceArray[i]));
		}
		System.out.println("-------------");
		Integer[][] sparse = sparse(chessboard);
		for (int i = 0; i < sparse.length; i++) {
			System.out.println(Arrays.toString(sparse[i]));
		}
		System.out.printf("开始将稀疏数组存盘...%d", System.currentTimeMillis());
		///sparse.getClass().getClassLoader().getResourceAsStream()
		///todo:系统路径分隔符
		///System.out.println(File.separator);
		System.out.println(sparse.getClass().getResource("/").getPath().replace("/", File.separator));
		///目录路径
		CATALOGUE_PATH=sparse.getClass().getResource("/").getPath().replace("/", File.separator).substring(1);
		Path filePath = Paths.get(sparse.getClass().getResource("/").getPath().replace("/", File.separator).substring(1), "map.data");

		///todo:FileWriter wr = new FileWriter(filePath.toString())	貌似不能转 utf-8,而是默认是用（ISO-8859-1 or US-ASCII）西方编码的
		try (OutputStreamWriter wr = new OutputStreamWriter(new FileOutputStream(filePath.toString()),"UTF-8")) {
			for (Integer[] row:
			sparse) {
				for (Integer data :
						row) {
					wr.write(data+"\t");
				}
				wr.write("\r\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.printf("结束将稀疏数组存盘...%d", System.currentTimeMillis());

		///将稀疏数组还原到内存
		Scanner scanner = new Scanner(System.in);
		System.out.println("///////请输入存档文件名：");
		if (scanner.hasNext()){
			String fileName = scanner.nextLine();
			Path fp = Paths.get(CATALOGUE_PATH, fileName);
			///从 map.data 直接转为 List<String[]>
			List<String[]> beforeSparseArr=new ArrayList<>();
			///System.out.println(fp);
			///todo:用 BufferedReader 读取比较高级，可以一行一行读
			try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fp.toString()), "UTF-8"))){
				String line;
				while((line=br.readLine()) != null){
					String[] strings = line.split(SEPARATOR);
					beforeSparseArr.add(strings);
					System.out.println(line);
				}

				System.out.println("///////稀疏数组中介形态转化完毕...");
				for (String[] item:
				beforeSparseArr) {
					System.out.println(Arrays.toString(item));
				}
				///还原 数组
				int[][] backArr=new int[Integer.valueOf(beforeSparseArr.get(0)[0]) ][Integer.valueOf(beforeSparseArr.get(0)[1])];
				for (int i = 1; i < beforeSparseArr.size(); i++) {
					int row=Integer.valueOf(beforeSparseArr.get(i)[0]);
					int col=Integer.valueOf(beforeSparseArr.get(i)[1]);
					backArr[row][col]=Integer.valueOf(beforeSparseArr.get(i)[2]);
				}
				System.out.println("///////稀疏数组还原原数组完毕...");
				print(backArr);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
